﻿using Unity;
using Sharp.Infrastructure.IoC;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using Unity.Lifetime;

namespace Sharp.Events
{
    /// <summary>
    /// 事件总线
    /// </summary>
    public class EventBus
    {
        private static readonly EventBus instance = new EventBus();

        /// <summary>
        /// 单例事件总线
        /// </summary>
        public static EventBus Instance => instance;

        /// <summary>
        /// 初始化
        /// </summary>
        public void Init()
        {
            //Type from, Type to
            //ServiceLocator.RegisterType(IEventHandler<LoginedEvent>)
        }


        #region 事件订阅
     
        /// <summary>
        /// 订阅事件
        /// </summary>
        /// <param name="eventHandler"></param>
        public void Subscribe<TEventData>(IEventHandler<TEventData> eventHandler)
            where TEventData : class, IEventData
        {
            var targetType = eventHandler.GetType();

            Subscribe(targetType);
        }
        /// <summary>
        /// 订阅事件
        /// </summary>
        /// <param name="targetType"></param>
        public void Subscribe(Type targetType)
        {
            foreach (var face in targetType.GetInterfaces())
            {
                if (ServiceLocator.Instance.IsRegistered(face))
                {
                    continue;
                }
                ServiceLocator.RegisterType(face, targetType, new ContainerControlledLifetimeManager());
            }
        }
        #endregion

        #region 取消订阅事件
        /// <summary>
        /// 取消订阅事件
        /// </summary>
        /// <typeparam name="TEventData">领域事件数据</typeparam>
        /// <param name="eventHandler"></param>
        public void Unsubscribe<TEventData>(IEventHandler<TEventData> eventHandler)
            where TEventData : class, IEventData
        {



        }
        #endregion

        #region 事件发布
        /// <summary>
        /// 发布事件，支持异步事件
        /// </summary>
        /// <typeparam name="TEventData"></typeparam>
        /// <param name="evnt"></param>
        public void Publish<TEventData>(TEventData evnt)
           where TEventData : class, IEventData
        {
            if (evnt == null)
                throw new ArgumentNullException(nameof(evnt));

            var handler = ServiceLocator.Instance.GetService<IEventHandler<TEventData>>();
            var asyncAttribute = handler.GetType()
                .GetCustomAttributes(typeof(AsyncAttribute), false)
                .OfType<AsyncAttribute>()
                .FirstOrDefault();
            if (asyncAttribute != null && asyncAttribute.IsAsync)
            {
                Task.Run(() =>
                {
                    handler.Handle(evnt);
                });
            }
            else
            {
                handler.Handle(evnt);
            }
        }

        #endregion

    }
}
